package virtorina.client.rooms;

import java.util.Iterator;
import java.util.LinkedList;

import virtorina.client.room.dto.RoomInfo;
import virtorina.client.room.rpc.GWTRoomsService;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

public class Rooms implements EntryPoint {

	@Override
	public void onModuleLoad() {
		tmp();
	}

	public void tmp() {
		GWTRoomsService.Util.getInstance().RoomsList(
				new AsyncCallback<LinkedList<RoomInfo>>() {

					@Override
					public void onSuccess(LinkedList<RoomInfo> result) {
						RootPanel.get("table").clear();
						RoomsList rl = new RoomsList(result.size());
						for (RoomInfo ri : result) {
							rl.add(ri);
						}
						RootPanel.get("table").add(rl);
						new addRoom(Rooms.this);
					}

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}
				});
	}

	class RoomEntity {
		static final int labelsSize = 70;
		int row;
		Grid grid;
		int id;
		String name;
		HTML viewName;
		HTML labelsShort;
		HTML labelsSLong;
		boolean collapse;
		int shift;

		Timer shifter = new Timer() {

			@Override
			public void run() {
				String s = getName();
				int lines = 1;
				if (!collapse) {
					lines = lablesLines;
				}
				if (s.length() <= lines * 20) {
					return;
				} else if (s.length() - shift < ((lines - 1) * 20) + 17) {
					shift = 0;
					return;
				} else {
					s = s.substring(shift, shift + ((lines - 1) * 20) + 17);
					viewName.setHTML(getShortInfo(s));
					shift++;
					return;
				}
			}

		};
		private boolean needLong;

		boolean setShortLabels(LinkedList<String> listSrc) {
			LinkedList<String> list = new LinkedList<String>(listSrc);

			int size = 0;
			StringBuilder sb = new StringBuilder();
			int types = 0;
			for (String s : list) {
				if (s.startsWith("#!")) {
					types++;
					s = s.substring(2);
					size += s.length() + 1;
					sb.append("<span class=\"label label\">" + s
							+ "</span> ");
				} else {
					break;
				}
			}
			for (int i = 0; i < types; i++) {
				list.removeFirst();
			}
			if (types == 4) {
				size = 6;
				sb = new StringBuilder(
						"<span class=\"label label-info\">All types</span> ");
			}
			if (list.isEmpty()) {
				labelsShort = new HTML(
						sb.toString()
								+ "<span class=\"label label-success\">All subjects</span>");
				return false;
			}
			for (String s : list) {
				if (size + s.length() > labelsSize) {
					labelsShort = new HTML(sb.toString() + "...");
					return true;
				} else {
					if (s.startsWith("#!")) {
						types++;
						s = s.substring(2);
						size += s.length() + 1;
						sb.append("<span class=\"label label-info\">" + s
								+ "</span> ");
					} else {
						sb.append("<span class=\"label\">" + s + "</span> ");
						size += s.length();
					}
				}
			}
			labelsShort = new HTML(sb.toString());
			return false;
		}

		int lablesLines = 1;

		void setLongLabels(LinkedList<String> listSrc) {
			LinkedList<String> list = new LinkedList<String>(listSrc);
			int size = 0;
			StringBuilder sb = new StringBuilder();
			int types = 0;
			for (String s : list) {
				if (s.startsWith("#!")) {
					types++;
					s = s.substring(2);
					size += s.length() + 1;
					sb.append("<span class=\"label\">" + s
							+ "</span> ");
				} else {
					break;
				}
			}
			for (int i = 0; i < types; i++) {
				list.removeFirst();
			}
			if (types == 4) {
				size = 6;
				sb = new StringBuilder(
						"<span class=\"label label-info\">All types</span> ");
			}
			for (String s : list) {
				if (size + s.length() > labelsSize) {
					sb.append("<br>");
					size = 0;
					lablesLines++;
				}
				sb.append("<span class=\"label\">" + s + "</span> ");
				size += s.length();
			}
			labelsSLong = new HTML(sb.toString());
		}

		MouseDownHandler LabelsHandler = new MouseDownHandler() {

			@Override
			public void onMouseDown(MouseDownEvent event) {
				if (needLong) {
					if (collapse) {
						expand();
					} else {
						collapse();
					}
				}

			}
		};

		RoomEntity(RoomInfo ri, int row, Grid grid) {
			super();
			this.row = row;
			this.grid = grid;
			this.id = ri.getId();
			this.collapse = true;
			this.name = ri.getName();
			viewName = new HTML(getShortInfo(name));
			viewName.setWidth("140px");
			needLong = setShortLabels(ri.getLabels());
			labelsShort.setWidth("500px");
			if (needLong) {
				setLongLabels(ri.getLabels());
				labelsSLong.setWidth("500px");
				labelsShort.addMouseDownHandler(LabelsHandler);
				labelsSLong.addMouseDownHandler(LabelsHandler);
			}
			grid.setText(row, 0, id + "");
			grid.setWidget(row, 1, viewName);
			grid.setWidget(row, 2, labelsShort);
			grid.setText(row, 3, ri.getPeople() + "");
			grid.setWidget(row, 4, new MyBtn(ri.getId()));

			viewName.addMouseMoveHandler(new MouseMoveHandler() {

				@Override
				public void onMouseMove(MouseMoveEvent event) {
					shifter.scheduleRepeating(200);
				}
			});
			viewName.addMouseDownHandler(LabelsHandler);
			viewName.addMouseOutHandler(new MouseOutHandler() {

				@Override
				public void onMouseOut(MouseOutEvent event) {
					shift = 0;
					shifter.cancel();
					viewName.setHTML(getShortInfo(getName()));

				}
			});
		}

		class MyBtn extends HTML {
			public MyBtn(final int id) {
				super("<button class=\"btn btn-mini\">Join</button>");
				this.addClickHandler(new ClickHandler() {

					@Override
					public void onClick(ClickEvent event) {
						Window.open("../room.html?id=" + id, "_self", "");
					}
				});
			}
		}

		String getName() {
			return name;
		}

		String getShortInfo(String nick) {
			StringBuilder name = new StringBuilder(nick);
			int lines = 1;
			if (!collapse) {
				lines = lablesLines;
			}
			if (name.length() > lines * 20) {
				name = new StringBuilder(name.subSequence(0,
						((lines - 1) * 20) + 17));
				name.append("...");
			}
			String h = new String("<span title='" + getName() + "'>"
					+ name.toString() + "</span>");
			return h;
		}

		void expand() {
			grid.setWidget(row, 2, labelsSLong);
			collapse = false;
			viewName.setHTML(getShortInfo(getName()));
		}

		void collapse() {
			grid.setWidget(row, 2, labelsShort);
			collapse = true;
			viewName.setHTML(getShortInfo(getName()));
		}
	}

	class RoomsList extends Grid {
		RoomsList(int size) {
			super(size, 5);
			super.addStyleName("table table-condensed table-striped");
			Element thead = DOM.createElement("thead");
			Element tr = DOM.createTR();
			DOM.appendChild(thead, tr);
			Element th;
			th = DOM.createTH();
			DOM.appendChild(tr, th);
			DOM.setInnerText(th, "#");
			th = DOM.createTH();
			DOM.appendChild(tr, th);
			DOM.setInnerText(th, "Name");
			th = DOM.createTH();
			DOM.appendChild(tr, th);
			DOM.setInnerText(th, "Labels");
			th = DOM.createTH();
			DOM.appendChild(tr, th);
			DOM.setInnerText(th, "People");
			th = DOM.createTH();
			DOM.appendChild(tr, th);

			// get the table element
			Element table = this.getElement();

			// and add the thead before the tbody
			DOM.insertChild(table, thead, 0);
			/*
			 * super.add(new HTML(
			 * "<table id=\"table\" class=\"table table-condensed table-striped\">"
			 * +
			 * "<thead><tr><th>#</th><th>Name</th><th>Labels</th><th>Peoples</th><th></th></tr></thead><tbody>"
			 * ));
			 */
		}

		void end() {
			super.add(new HTML("</tbody></table>"));
		}

		int added = 0;

		public void add(RoomInfo ri) {
			add(ri, added++);
		}

		public void add(RoomInfo ri, int k) {
			new RoomEntity(ri, k, this);
		}

		public boolean remove(int id) {
			Iterator<Widget> i = super.iterator();
			int k = 0;
			// @TODO room remove
			/*
			 * while (i.hasNext()) { if (((RoomEntity) i.next()).id == id) {
			 * super.remove(k); return true; } k++; }
			 */
			return false;
		}
	}
}
